<!DOCTYPE html>
<html>
<head>
  <title>Physics Pulley System Diagram</title>
  <style>
    canvas {
      border: 1px solid #ccc;
    }
  </style>
</head>
<body>
  <canvas id="physics-canvas" width="450" height="480"></canvas>
  <script>
    const canvas = document.getElementById('physics-canvas');
    const ctx = canvas.getContext('2d');

    // Function to draw the diagram
    function drawDiagram() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.strokeStyle = 'black';
      ctx.fillStyle = 'black';

      // --- Define coordinates and dimensions ---
      const cx = 225; // Center X of the pulley
      const pulleyTopY = 80;
      const pulleyRadius = 60;
      const cy = pulleyTopY + pulleyRadius; // Center Y of the pulley
      const ceilingY = pulleyTopY - 20;

      // 1. Draw Ceiling
      ctx.lineWidth = 2;
      ctx.beginPath();
      ctx.moveTo(cx - 150, ceilingY);
      ctx.lineTo(cx + 150, ceilingY);
      ctx.stroke();
      // Ceiling hatches
      ctx.lineWidth = 1;
      for (let i = 0; i < 300; i += 20) {
        ctx.moveTo(cx - 150 + i, ceilingY);
        ctx.lineTo(cx - 150 + i - 10, ceilingY - 10);
      }
      ctx.stroke();

      // 2. Draw Pulley
      ctx.lineWidth = 2;
      // Support bracket
      ctx.strokeRect(cx - 10, ceilingY, 20, cy - ceilingY);
      
      // Pulley wheel with hatching
      ctx.save();
      ctx.beginPath();
      ctx.arc(cx, cy, pulleyRadius, 0, 2 * Math.PI);
      ctx.stroke();
      ctx.clip(); // Clip the hatching to the circle's area
      ctx.lineWidth = 1;
      ctx.beginPath();
      const hatchSpacing = 8;
      for (let i = -pulleyRadius * 2; i < pulleyRadius * 2; i += hatchSpacing) {
        ctx.moveTo(cx + i, cy - pulleyRadius * 2);
        ctx.lineTo(cx + i + pulleyRadius * 2, cy + pulleyRadius * 2);
      }
      ctx.stroke();
      ctx.restore();

      // Axle
      ctx.lineWidth = 1.5;
      ctx.beginPath();
      ctx.arc(cx, cy, 8, 0, 2 * Math.PI);
      ctx.fillStyle = 'white';
      ctx.fill();
      ctx.stroke();
      // Axle details (cross pattern)
      ctx.beginPath();
      const axleR = 6;
      ctx.moveTo(cx - axleR, cy); ctx.lineTo(cx + axleR, cy);
      ctx.moveTo(cx, cy - axleR); ctx.lineTo(cx, cy + axleR);
      ctx.moveTo(cx - axleR * 0.707, cy - axleR * 0.707); ctx.lineTo(cx + axleR * 0.707, cy + axleR * 0.707);
      ctx.moveTo(cx + axleR * 0.707, cy - axleR * 0.707); ctx.lineTo(cx - axleR * 0.707, cy + axleR * 0.707);
      ctx.stroke();

      // 3. Draw Rope
      const ropeLX = cx - pulleyRadius;
      const ropeRX = cx + pulleyRadius;
      const weightTopY = 240;
      
      ctx.lineWidth = 1.5;
      ctx.beginPath();
      ctx.moveTo(ropeLX, 400); // Bottom of left rope
      ctx.lineTo(ropeLX, cy); // Left rope up to pulley
      ctx.arc(cx, cy, pulleyRadius, Math.PI, 0); // Arc over pulley
      ctx.lineTo(ropeRX, weightTopY); // Right rope down to weight
      ctx.stroke();

      // 4. Draw Person (A)
      const handsY = 260;
      ctx.lineWidth = 1.5;
      // Head
      ctx.beginPath();
      ctx.fillStyle = '#222';
      ctx.arc(ropeLX + 10, handsY + 12, 6, 0, Math.PI * 2);
      ctx.fill();
      // Body and limbs (outline style)
      ctx.beginPath();
      ctx.moveTo(ropeLX, handsY); // Upper hand
      ctx.lineTo(ropeLX + 10, handsY + 20); // Upper arm to shoulder
      ctx.lineTo(ropeLX + 18, handsY + 22); // Right shoulder
      ctx.lineTo(ropeLX + 14, handsY + 50); // Torso to waist
      ctx.lineTo(ropeLX + 25, handsY + 85); // Right leg to foot
      ctx.moveTo(ropeLX + 14, handsY + 50); // Back to waist
      ctx.lineTo(ropeLX + 2, handsY + 80); // Left leg to foot
      ctx.moveTo(ropeLX + 18, handsY + 22); // Right shoulder
      ctx.lineTo(ropeLX + 2, handsY + 5); // Right arm to lower hand
      ctx.stroke();
      
      // 5. Draw Weight (B)
      const weightW = 60;
      const weightH = 80;
      const weightX = ropeRX - weightW / 2;
      const weightY = weightTopY;
      ctx.lineWidth = 2;
      ctx.strokeRect(weightX, weightY, weightW, weightH);
      // Cross-hatch pattern for weight
      ctx.save();
      ctx.beginPath();
      ctx.rect(weightX, weightY, weightW, weightH);
      ctx.clip();
      ctx.lineWidth = 1;
      ctx.strokeStyle = '#333';
      ctx.beginPath();
      const crossHatchSpacing = 10;
      for (let i = -weightH; i < weightW; i += crossHatchSpacing) {
        ctx.moveTo(weightX + i, weightY);
        ctx.lineTo(weightX + i + weightH, weightY + weightH);
      }
      for (let i = 0; i < weightW + weightH; i += crossHatchSpacing) {
        ctx.moveTo(weightX + i, weightY);
        ctx.lineTo(weightX + i - weightH, weightY + weightH);
      }
      ctx.stroke();
      ctx.restore();

      // 6. Add Labels
      ctx.fillStyle = 'black';
      ctx.font = '24px Times New Roman';
      ctx.textAlign = 'left';
      // Label A
      ctx.fillText('A', ropeLX - 40, 320);
      // Label B
      ctx.fillText('B', ropeRX + 25, 300);
      // Label O
      ctx.font = 'italic 20px Times New Roman';
      ctx.fillText('O', cx + 10, cy + 25);
      // Bottom text
      ctx.font = '24px "Songti SC", "SimSun", serif';
      ctx.textAlign = 'center';
      ctx.fillText('习题 3-19 图', cx, 440);
    }

    // Execute drawing
    drawDiagram();
  </script>
</body>
</html>